package es.esi.gemde.methodmanager.ui.actions;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

import es.esi.gemde.methodmanager.methodmodel.method.GEMDEMethod;
import es.esi.gemde.methodmanager.transformations.MethodModel2Plugintransformation;
import es.esi.gemde.modeltransformator.ModelTransformatorPlugin;
import es.esi.gemde.modeltransformator.exceptions.NoSuchEngineException;
import es.esi.gemde.modeltransformator.exceptions.TransformationEngineException;
import es.esi.gemde.modeltransformator.service.AbstractJavaTransformation;

/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be 
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class GenerateCheatSheetPluginAction implements IWorkbenchWindowActionDelegate {

	private IStructuredSelection selection;
	
	private IWorkbenchWindow window;
	/**
	 * The constructor.
	 */
	public GenerateCheatSheetPluginAction() {
	}

	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {		
		String pathName = "";
		//Try to get the .method file from the user selection
		if(selection.size()==1){
			for (Object o : selection.toList()) {
				if(o instanceof IFile && (((IFile) o).getFileExtension().toLowerCase().equals("method"))){
					pathName = ((IFile) o).getLocation().toOSString();
				}
					
			}
		}
		//If no valid file is selected, show a file dialog to choose one
		if(pathName.equals("")){
			FileDialog fileDialog = new FileDialog(new Shell());
			fileDialog.setText("Select a .method cheatsheet file");
			  fileDialog.setFilterExtensions(new String[]{"*.method"});
			  String location=fileDialog.open();
			  if (location != null) {
				  pathName = location;
			  }
		}
		//If a valid file is selected, load the model and generate
		if(!pathName.equals("")){
			ResourceSet rs = new ResourceSetImpl();
			Resource r = rs.getResource(URI.createFileURI(pathName), true);
			Vector<EObject> inputs = new Vector<EObject>();
			GEMDEMethod model = null;
			
			TreeIterator<EObject> i = r.getAllContents();
			while (i.hasNext() && inputs.size() == 0) {
				EObject o = i.next();
				if (o instanceof GEMDEMethod) {
					model = (GEMDEMethod) o;
					inputs.add(o);
				}
			}
	
			try {
				//Generate the cheatsheet plugin
				ModelTransformatorPlugin.getService().executeTransformation(inputs, MethodModel2Plugintransformation.TRANSFORMATION_NAME, AbstractJavaTransformation.ENGINE_NAME, ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString());
				//Generate the cheatsheet xml files
				ModelTransformatorPlugin.getService().executeTransformation(inputs, "GEMDEMethod2Cheatsheets", "MOFScript", ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString() + File.separator + model.getProjectName());
				
				//Refresh the project
				ResourcesPlugin.getWorkspace().getRoot().getProject(((GEMDEMethod) inputs.get(0)).getProjectName()).refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
			} catch (TransformationEngineException e) {
				MessageDialog.openError(
						window.getShell(),
						"Error",
						e.getMessage());
			} catch (IllegalArgumentException e) {
				MessageDialog.openError(
						window.getShell(),
						"Error",
						e.getMessage());
			} catch (NoSuchEngineException e) {
				MessageDialog.openError(
						window.getShell(),
						"Error",
						e.getMessage());
			} catch (IOException e) {
				MessageDialog.openError(
						window.getShell(),
						"Error",
						e.getMessage());
			} catch (CoreException e) {
				MessageDialog.openError(
						window.getShell(),
						"Error",
						e.getMessage());
			}
		}
	}

	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
		if (selection instanceof IStructuredSelection)
			this.selection = (IStructuredSelection) selection;
	}

	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}

	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
		this.window = window;
	}
}